package com.lld.im.service.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ecode.imecode.pack.user.UserModifyPack;
import com.lld.im.common.ResponseVO;
import com.lld.im.common.config.AppConfig;
import com.lld.im.common.constants.Constants;
import com.lld.im.common.enums.DelFlagEnum;
import com.lld.im.common.enums.UserErrorCode;
import com.lld.im.common.enums.UserTypeEnum;
import com.lld.im.common.enums.commond.UserEventCommand;
import com.lld.im.common.exception.ApplicationException;
import com.lld.im.common.model.ClientInfo;
import com.lld.im.common.model.UserSession;
import com.lld.im.common.utils.SigAPI;
import com.lld.im.service.callback.CallBackServer;
import com.lld.im.service.group.service.ImGroupService;
import com.lld.im.service.inspector.SignCheck;
import com.lld.im.service.rpc.controller.RpcServerController;
import com.lld.im.service.rpc.model.req.ZkUserInfoReq;
import com.lld.im.service.rpc.server.ZkRpcServer;
import com.lld.im.service.user.dao.ImUserDataEntity;
import com.lld.im.service.user.dao.mapper.ImUserDataMapper;
import com.lld.im.service.user.model.req.*;
import com.lld.im.service.user.model.resp.GetUserInfoResp;
import com.lld.im.service.user.model.resp.ImportUserResp;
import com.lld.im.service.user.model.resp.UserLoginResp;
import com.lld.im.service.user.service.ImUserService;
import com.lld.im.service.utils.MessageProducer;
import com.lld.im.service.utils.RedisUserSessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @description:
 * @author: lld
 * @version: 1.0
 */
@Service
public class ImUserviceImpl implements ImUserService {

    @Autowired
    ImUserDataMapper imUserDataMapper;


    @Autowired
    ImGroupService imGroupService;

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private CallBackServer callBackServer;

    @Autowired
    private MessageProducer messageSender;



    @Override
    public ResponseVO importUser(ImportUserReq req) {

        if (req.getUserData().size() > 100) {
            return ResponseVO.errorResponse(UserErrorCode.IMPORT_SIZE_BEYOND);
        }

        ImportUserResp resp = new ImportUserResp();
        List<String> successId = new ArrayList<>();
        List<String> errorId = new ArrayList<>();

        for (ImUserDataEntity data :
                req.getUserData()) {
            try {
                data.setAppId(req.getAppId());
                int insert = imUserDataMapper.insert(data);
                if (insert == 1) {
                    successId.add(data.getUserId());
                }
            } catch (Exception e) {
                e.printStackTrace();
                errorId.add(data.getUserId());
            }
        }

        resp.setErrorId(errorId);
        resp.setSuccessId(successId);
        return ResponseVO.successResponse(resp);
    }

    @Override
    public ResponseVO<GetUserInfoResp> getUserInfo(GetUserInfoReq req) {
        QueryWrapper<ImUserDataEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_id", req.getAppId());
        queryWrapper.in("user_id", req.getUserIds());
        queryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode());

        List<ImUserDataEntity> userDataEntities = imUserDataMapper.selectList(queryWrapper);
        HashMap<String, ImUserDataEntity> map = new HashMap<>();

        for (ImUserDataEntity data :
                userDataEntities) {
            map.put(data.getUserId(), data);
        }

        List<String> failUser = new ArrayList<>();
        for (String uid :
                req.getUserIds()) {
            if (!map.containsKey(uid)) {
                failUser.add(uid);
            }
        }

        GetUserInfoResp resp = new GetUserInfoResp();
        resp.setUserDataItem(userDataEntities);
        resp.setFailUser(failUser);
        return ResponseVO.successResponse(resp);
    }

//    @Operation()
    @Override
    public ResponseVO<ImUserDataEntity> getSingleUserInfo(String userId, Integer appId) {
        QueryWrapper objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("app_id", appId);
        objectQueryWrapper.eq("user_id", userId);
        objectQueryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode());

        ImUserDataEntity ImUserDataEntity = imUserDataMapper.selectOne(objectQueryWrapper);
        if (ImUserDataEntity == null) {
            return ResponseVO.errorResponse(UserErrorCode.USER_IS_NOT_EXIST);
        }

        return ResponseVO.successResponse(ImUserDataEntity);
    }

    @Override
    public ResponseVO deleteUser(DeleteUserReq req) {
        ImUserDataEntity entity = new ImUserDataEntity();
        entity.setDelFlag(DelFlagEnum.DELETE.getCode());

        List<String> errorId = new ArrayList();
        List<String> successId = new ArrayList();

        for (String userId :
                req.getUserId()) {
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("app_id", req.getAppId());
            wrapper.eq("user_id", userId);
            wrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode());
            int update = 0;

            try {
                update = imUserDataMapper.update(entity, wrapper);
                if (update > 0) {
                    successId.add(userId);
                } else {
                    errorId.add(userId);
                }
            } catch (Exception e) {
                errorId.add(userId);
            }
        }

        ImportUserResp resp = new ImportUserResp();
        resp.setSuccessId(successId);
        resp.setErrorId(errorId);
        return ResponseVO.successResponse(resp);
    }

    @Override
    @Transactional
    public ResponseVO modifyUserInfo(ModifyUserInfoReq req) {
        QueryWrapper query = new QueryWrapper<>();
        query.eq("app_id", req.getAppId());
        query.eq("user_id", req.getUserId());
        query.eq("del_flag", DelFlagEnum.NORMAL.getCode());
        ImUserDataEntity user = imUserDataMapper.selectOne(query);
        if (user == null) {
            throw new ApplicationException(UserErrorCode.USER_IS_NOT_EXIST);
        }

        ImUserDataEntity update = new ImUserDataEntity();
        BeanUtils.copyProperties(req, update);

        update.setAppId(null);
        update.setUserId(null);
        int update1 = imUserDataMapper.update(update, query);
        if (update1 == 1) {
            //TODO 用户资料修改 通知其它客户端
            UserModifyPack userModifyPack = new UserModifyPack();
            BeanUtils.copyProperties(req, userModifyPack);
            ClientInfo clientInfo = new ClientInfo();
            clientInfo.setAppId(req.getAppId());
            clientInfo.setClientType(req.getClientType());
            clientInfo.setImei(req.getImei());
            messageSender.sendToAllUserOrExpSelf(req.getUserId(), req.getClientType(), req.getImei(), UserEventCommand.USER_MODIFY,
                    userModifyPack, req.getAppId());
            //服务回调
            if (appConfig.isModifyUserAfterCallback()) {
                callBackServer.callBack(req.getAppId(), Constants.CallbackCommand.ModifyUserAfter,
                        JSONObject.toJSONString(req));
            }
            return ResponseVO.successResponse();
        }
        throw new ApplicationException(UserErrorCode.MODIFY_USER_ERROR);
    }


    @Override
    public ResponseVO login(LoginReq req) {
        //测试接口用 暂不检验密码
        LambdaQueryWrapper<ImUserDataEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ImUserDataEntity::getUserId,req.getUserId())
                        .eq(ImUserDataEntity::getAppId,req.getAppId());
        ImUserDataEntity userDataEntity = imUserDataMapper.selectOne(wrapper);
        if(userDataEntity!=null){
            UserLoginResp userLoginResp = new UserLoginResp();
            BeanUtils.copyProperties(userDataEntity,userLoginResp);
            userLoginResp.setAppId(req.getAppId());
            userLoginResp.setClientType(req.getClientType());
            //添加用户签名
            String signU = new SigAPI(req.getAppId(), appConfig.getPrivateKey())
                    .genUserSig(userDataEntity.getUserId());
            userLoginResp.setSign(signU);
            //TODO 写入redis中 这里不会写入redis
            //TODO 用户登录后 会返回userSign 网关层对此会进行二次检验 检验的同时保存userSession
            //TODO 在用户登录之后 返回im的服务信息
//            ZkUserInfoReq zkUserInfoReq = new ZkUserInfoReq();
//            zkUserInfoReq.setUserId(req.getUserId());
//            zkUserInfoReq.setClientType();
//            zkRpcServer.getZkServer()
            return ResponseVO.successResponse(userLoginResp);
        }
        return ResponseVO.errorResponse(UserErrorCode.USER_IS_NOT_EXIST);
    }

    @Override
    public ResponseVO registerUser(RegisterUserReq req) {
        Integer integer = imUserDataMapper.selectCount(new LambdaQueryWrapper<ImUserDataEntity>()
                .eq(ImUserDataEntity::getUserId, req.getUserId())
                .eq(ImUserDataEntity::getAppId, req.getAppId()));
        if(integer>0) {
            return ResponseVO.errorResponse(UserErrorCode.USER_EXIT);
        }
        ImUserDataEntity userDataEntity = new ImUserDataEntity();
        BeanUtils.copyProperties(req,userDataEntity);
        userDataEntity.setUserType(UserTypeEnum.NORMAL_USER.getCode());
        int insert = imUserDataMapper.insert(userDataEntity);
        if(insert==0){
            return ResponseVO.errorResponse();
        }
        UserLoginResp userLoginResp = new UserLoginResp();
        BeanUtils.copyProperties(req,userLoginResp);
        userLoginResp.setClientType(req.getClientType());
        String signU = new SigAPI(req.getAppId(), appConfig.getPrivateKey())
                .genUserSig(userDataEntity.getUserId());
        userLoginResp.setSign(signU);
        return ResponseVO.successResponse();
    }

}
